package cn.xinfei.xdecision.manager.controller.component.decisiontable;


import cn.xinfei.xdecision.common.model.common.PageResult;
import cn.xinfei.xdecision.common.model.common.ResponseEntityBuilder;
import cn.xinfei.xdecision.common.model.common.ResponseEntityDto;
import cn.xinfei.xdecision.common.model.common.requestParam.AssemblyRuleCodeReq;
import cn.xinfei.xdecision.common.model.component.decisiontable.DecisionTablesVersion;
import cn.xinfei.xdecision.common.model.component.decisiontable.vo.DecisionTablesVersionListVo;
import cn.xinfei.xdecision.common.model.component.decisiontable.vo.DecisionTablesVersionVo;
import cn.xinfei.xdecision.common.service.component.decisiontable.DecisionTablesVersionService;
import cn.xinfei.xdecision.common.utils.constant.OperateNameConst;
import cn.xinfei.xdecision.common.utils.constant.OperateTypeEnum;
import cn.xinfei.xdecision.common.utils.constant.RedisConstant;
import cn.xinfei.xdecision.common.utils.exception.ApiException;
import cn.xinfei.xdecision.common.utils.exception.enums.ErrorCodeEnum;
import cn.xinfei.xdecision.manager.web.aop.ArchivesLog;
import com.baomidou.mybatisplus.extension.api.ApiController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.text.MessageFormat;
import java.util.List;
import java.util.Objects;


/**
 * 决策表版本controller
 *
 * @author zdy
 * @since 2023-03-17
 */
@Api(tags = "组件中心-决策表")
@RestController
@RequestMapping("/v3/decisionTables/version")
@Slf4j
public class DecisionTablesVersionController extends ApiController {

    @Resource
    private DecisionTablesVersionService versionService;

    @Resource
    private RedissonClient redissonClient;

    @ApiOperation(value = "决策表_查询的版本详情")
    @PostMapping("/getVersionInfo/{versionId}")
    public ResponseEntityDto<DecisionTablesVersionVo> getVersionInfo(@PathVariable Long versionId) {
        return ResponseEntityDto.success(versionService.queryById(versionId));
    }

    @ApiOperation(value = "决策表_新建版本")
    @PostMapping("/addVersion")
    @ArchivesLog(type = OperateTypeEnum.CREATE,name = OperateNameConst.ComponentOpt.SAVE_VERSION)
    public ResponseEntityDto<Long> addVersion(@RequestBody DecisionTablesVersionVo version) {
        if (StringUtils.isEmpty(version.getDecisionTablesCode())) {
            return ResponseEntityBuilder.buildErrorResponse(ErrorCodeEnum.DECISION_CODE_CAN_NOT_NULL);
        }
        //获取分布式锁
        String key = MessageFormat.format(RedisConstant.RISK_ENGINE_BASIC_INFO_KEY,
                RedisConstant.COMPONENT_KEY,
                RedisConstant.DECISION_TABLE,
                version.getDecisionTablesCode());
        RLock lock = redissonClient.getLock(key);

        if (!lock.tryLock()) {
            return ResponseEntityBuilder.buildErrorResponse(ErrorCodeEnum.RECEIPT_CONCURRENT_OPERATE_ERROR);
        }
        try {
            return ResponseEntityDto.success(versionService.checkAndAddVersion(version));
        } catch (ApiException e) {
            log.error("新建版本业务异常", e);
            return ResponseEntityBuilder.buildErrorResponse(e.getErrCode(), e.getMessage());
        } catch (Exception e) {
            log.error("新建版本未知异常", e);
            return ResponseEntityBuilder.buildErrorResponse(ErrorCodeEnum.SERVER_ERROR);
        } finally {
            lock.unlock();
        }
    }

    @ApiOperation(value = "决策表_锁定版本")
    @PostMapping(value = "/lockDecisionTables/{versionId}")
    @ArchivesLog(type = OperateTypeEnum.UPDATE,name = OperateNameConst.ComponentOpt.LOCK_VERSION)
    public ResponseEntityDto<String> lockDecisionTables(@PathVariable Long versionId) {
        DecisionTablesVersion decisionTablesVersion = versionService.getById(versionId);
        if (Objects.isNull(decisionTablesVersion)) {
            throw new ApiException(ErrorCodeEnum.COMPONENT_NOT_EXIST);
        }
        //获取分布式锁
        String key = MessageFormat.format(RedisConstant.RISK_ENGINE_BASIC_INFO_KEY,
                RedisConstant.COMPONENT_KEY,
                RedisConstant.DECISION_TABLE,
                decisionTablesVersion.getDecisionTablesCode());
        RLock lock = redissonClient.getLock(key);
        if (!lock.tryLock()) {
            return ResponseEntityBuilder.buildErrorResponse(ErrorCodeEnum.RECEIPT_CONCURRENT_OPERATE_ERROR);
        }
        try {
            versionService.lockDecisionTables(decisionTablesVersion);
            return ResponseEntityDto.success("锁定规则及版本成功!");
        } catch (ApiException e) {
            log.error("锁定规则及版本业务异常", e);
            return ResponseEntityBuilder.buildErrorResponse(e.getErrCode(), e.getMessage());
        } catch (Exception e) {
            log.error("锁定规则及版本未知异常", e);
            return ResponseEntityBuilder.buildErrorResponse(ErrorCodeEnum.SERVER_ERROR);
        } finally {
            lock.unlock();
        }

    }

    @ApiOperation(value = "决策表_查看版本列表")
    @PostMapping(value = "/listByDecisionTableCode")
    public ResponseEntityDto<PageResult<List<DecisionTablesVersionListVo>, DecisionTablesVersion>> listByDecisionTableCode(@Valid @RequestBody AssemblyRuleCodeReq req) {
        return versionService.listByDecisionTableCode(req);
    }

}
